package com.ruoyi.common.log.aspect;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.ConvertUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.domain.AjaxResultDatas;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Dict;
import com.ruoyi.common.log.annotation.DictDetail;
import com.ruoyi.system.api.RemoteDictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;


/**
 *  字典aop类
 * @author  lcj
 */
@Aspect
@Component
@Slf4j
public class DictAspect {

    @Autowired
    private RemoteDictService dictService;

    // 定义切点Pointcut
    @Pointcut("execution(public * com.ruoyi.*.controller..*.*(..))")
    public void excudeService() {
    }

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

        return this.parseDictText(pjp);
    }

    /**
     * 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入
     */
    private Object parseDictText(ProceedingJoinPoint joinPoint) throws Throwable{
        Object result = joinPoint.proceed();
        if (result instanceof TableDataInfo) {
            List<JSONObject> items = new ArrayList<>();
            for (Object record : ((TableDataInfo) result).getRows()) {
                ObjectMapper mapper = new ObjectMapper();
                String json = "{}";
                try {
                    //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
                    json = mapper.writeValueAsString(record);
                } catch (JsonProcessingException e) {
                    log.error("json解析失败" + e.getMessage(), e);
                }
                JSONObject item = this.oConvertFiled(JSONObject.parseObject(json), record);
                items.add(item);
            }
            ((TableDataInfo) result).setRows(items);

        }else if (result instanceof AjaxResult){
            MethodSignature signature = ((MethodSignature) joinPoint.getSignature());
            //得到拦截的方法
            Method method = signature.getMethod();
            //判断方法是够有这个注解
            if (method.isAnnotationPresent(DictDetail.class)) {
                // 获取 DictDetail 注解的实例
                DictDetail annotation = method.getAnnotation(DictDetail.class);
                if (!annotation.isList()) {
                    AjaxResult record=((AjaxResult) result);
                    ObjectMapper mapper = new ObjectMapper();
                    String json = "{}";
                    try {
                        //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
                        json = mapper.writeValueAsString(record);
                    } catch (JsonProcessingException e) {
                        log.error("json解析失败" + e.getMessage(), e);
                    }
                    JSONObject resJson = JSONObject.parseObject(json,JSONObject.class, JSONReader.Feature.IgnoreSetNullValue);
                    if (Objects.nonNull(resJson) && Objects.equals(String.valueOf(HttpStatus.SUCCESS), resJson.getString("code"))) {
                        if (StringUtils.isNotEmpty(resJson.getString("data"))) {
                            JSONObject item = this.oConvertFiled(resJson.getJSONObject("data"), record.getData());
                            return AjaxResult.success(item);
                        }
                    }
                }
            }
        }else if (result instanceof AjaxResultDatas){
            MethodSignature signature = ((MethodSignature) joinPoint.getSignature());
            //得到拦截的方法
            Method method = signature.getMethod();
            //判断方法是够有这个注解
            if (method.isAnnotationPresent(DictDetail.class)) {
                // 获取 DictDetail 注解的实例
                DictDetail annotation = method.getAnnotation(DictDetail.class);
                //是否是列表
                if (annotation.isList()) {
                    List<JSONObject> resJsonList = new ArrayList<>();
                    ObjectMapper mapper = new ObjectMapper();
                    if (CollectionUtil.isNotEmpty(((AjaxResultDatas) result).getData())) {
                        String json = "{}";
                        for (Object obj : ((AjaxResultDatas) result).getData()) {
                            try {
                                json = mapper.writeValueAsString(obj);
                            } catch (JsonProcessingException e) {
                                log.error("json解析失败" + e.getMessage(), e);
                            }
                            JSONObject item = this.oConvertFiled(JSONObject.parseObject(json,JSONObject.class, JSONReader.Feature.IgnoreSetNullValue), obj);
                            resJsonList.add(item);
                        }
                        return AjaxResultDatas.success(resJsonList);
                    }
                }
            }
        }
        return result;
    }

    /**
     *  翻译字典文本
     * @return String
     */
    private JSONObject oConvertFiled(JSONObject item, Object record) {
        for (Field field : ConvertUtils.getAllFields(record)) {
            if (field.getAnnotation(Dict.class) != null) {
                String code = field.getAnnotation(Dict.class).dicCode();
                String text = field.getAnnotation(Dict.class).dicText();
                String table = field.getAnnotation(Dict.class).dictTable();
                String key = String.valueOf(item.get(field.getName()));
                //翻译字典值对应的txt
                String textValue = translateDictValue(code, text, table, key);
                item.put(field.getName() + Constants.DICT_TEXT_SUFFIX, textValue);
            }
            //date类型默认转换string格式化日期
            if (field.getType().getName().equals("java.util.Date")&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){
                SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName()))));
            }
        }

        return item;
    }


    /**
     *  翻译字典文本
     * @return String
     */
    private String translateDictValue(String code, String text, String table, String key) {
    	if(ConvertUtils.isEmpty(key)) {
    		return null;
    	}
        StringBuilder textValue=new StringBuilder();
        String[] keys = key.split(",");
        for (String k : keys) {
            String tmpValue;
            if (k.trim().length() == 0) {
                continue; //跳过循环
            }
            if (StringUtils.isNotEmpty(table)){
                R<String> r=dictService.queryTableDictTextByKey(table,text,code,k.trim(),SecurityConstants.INNER);
                tmpValue= r.getData();
            }else {
                R<String> r=dictService.getDictLabel(code, k.trim(), SecurityConstants.INNER);
                tmpValue = r.getData();
            }
            if (tmpValue != null) {
                if (!"".equals(textValue.toString())) {
                    textValue.append(",");
                }
                textValue.append(tmpValue);
            }

        }
        return textValue.toString();
    }

}
